﻿using System.Collections.Generic;
using System.IO;
using System.Reflection;

using Vestras.StarCraft2.Luna.Parser.Ast;

namespace Vestras.StarCraft2.Luna.Parser {
    public sealed class FileNetworkParser {
        public const string GrammarTableFileName = "Vestras.StarCraft2.Luna.Parser.galaxy.cgt";

        Stream grammarTableStream;
        FileNetwork network;
        SkeletonParser skeletonParser;

        public static string[] CurrentlyIncludedFiles = null;

        public FileNetwork Network {
            get {
                return network;
            }
        }

        static FileNetworkParser instance;
        public static FileNetworkParser Instance {
            get {
                return instance;
            }
        }

        public IEnumerable<Entity> ParseNetwork(FileNetwork network, bool reportErrors, out bool valid) {
            valid = true;
            this.network = network;
            SkeletonParser.ClearEntities();
            if (skeletonParser == null) {
                skeletonParser = new SkeletonParser(grammarTableStream);
            }

            List<string> currentlyIncludedFiles = new List<string>();
            foreach (string includedFile in network.IncludedFiles) {
                currentlyIncludedFiles.Add(includedFile);
            }

            CurrentlyIncludedFiles = currentlyIncludedFiles.ToArray();
            skeletonParser.reportErrors = reportErrors;
            skeletonParser.valid = true;
            foreach (string includedFile in network.IncludedFiles) {
                skeletonParser.CurrentFileName = includedFile;
                try {
                    using (StreamReader reader = new StreamReader(includedFile)) {
                        skeletonParser.Parse(reader.ReadToEnd());
                    }
                } catch (IOException exception) {
                    if (reportErrors) {
                        ErrorSink.AddError(ErrorSink.Error.Create(exception.Message, 0, 0, 0, 0, includedFile));
                    }
                } catch (System.NullReferenceException exception) {
                    if (reportErrors) {
                        ErrorSink.AddError(ErrorSink.Error.Create(exception.Message, 0, 0, 0, 0, includedFile));
                    }
                }
            }

            valid = skeletonParser.valid;
            return SkeletonParser.Entities;
        }

        private FileNetworkParser() {
            Assembly assembly = GetType().Assembly;
            grammarTableStream = assembly.GetManifestResourceStream(GrammarTableFileName);
        }

        static FileNetworkParser() {
            instance = new FileNetworkParser();
        }
    }
}
